package org.sky.mongodb.dao.impl;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;

import org.sky.mongodb.dao.IMongoDBDao;
import org.sky.mongodb.dao.entity.MPO;
import org.sky.mongodb.dao.entity.Page;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import com.mongodb.WriteResult;

public class MongoDBDaoImpl implements IMongoDBDao {

	private MongoTemplate mongoTemplate;

	public MongoTemplate getMongoTemplate() {
		return mongoTemplate;
	}

	public void setMongoTemplate(MongoTemplate mongoTemplate) {
		this.mongoTemplate = mongoTemplate;
	}

	@Override
	public <T extends MPO> List<T> getAll(String collcetionName, Class<T> clazz) {
		return mongoTemplate.findAll(clazz, collcetionName);
	}

	@Override
	public <T extends MPO> void insert(T e, String collectionName) {
		 mongoTemplate.insert(e, collectionName);
	}

	@Override
	public long findCount(String collectionName) {
		return mongoTemplate.count(new Query(), collectionName);
	}

	@Override
	public <T extends MPO> T findByID(String collcetionName,Class<T> clazz ,String id) {
		return getMongoTemplate().findById(id, clazz, collcetionName);
	}

	@Override
	public <T extends MPO> T findOne(String collcetionName, Class<T> clazz,Query query) {
		  return mongoTemplate.findOne(query, clazz, collcetionName);
	}

	@Override
	public <T extends MPO> List<T> find(Query query, String collcetionName,Class<T> clazz) {
		return mongoTemplate.find(query,clazz,collcetionName);
	}

	@Override
	public <T extends MPO> List<T> findByPage(String collcetionName,Class<T> clazz, Page page) {
	    long count = this.findCount(collcetionName); 
        int pageNumber = page.getPageNumber();  
        int pageSize = page.getPageSize();  
        Query query = new Query();
        query.skip((pageNumber - 1) * pageSize).limit(pageSize);  
        List<T> rows = this.find(query, collcetionName, clazz);
        return rows;
	}

	@Override
	public Boolean removeAll(String collcetionName) {
		mongoTemplate.remove(new Query(), collcetionName);
		return true;
	}

	@Override
	public Boolean removeById(String collcetionName, String id) {
		mongoTemplate.remove(new Query().addCriteria(new Criteria("_id").is(id)), collcetionName);
		return true;
	}

	@Override
	public <T extends MPO> Boolean update(String collectionName ,T t,Class<T> clazz) {
		Query query = new Query();
		Update update = new Update();
		Field [] fields = t.getClass().getDeclaredFields();
		try{
			for(Field field : fields){
					String name = field.getName();
					String upperName = name.substring(0, 1).toUpperCase() + name.substring(1);
					Method method = t.getClass().getMethod("get" + upperName);
					Object value = method.invoke(t);
					if("id".equals(name)){
						query.addCriteria(new Criteria("_id").is(value));
					}else{
						update.set(name, value);
					}
			}
		}catch(Exception e){
			
		}
		this.mongoTemplate.updateFirst(query, update, collectionName);
		return true;
	}
}
